Yao Lirong's Blog

P1031 均分纸牌

2019/06/04

题目来源:洛谷P1031 均分纸牌


标解

注意本题中平均数的运用

首先,一定要想到每堆排的张数减去平均张数,这样,题目就变成了移动正数,加到负数中,是大家都变成了0,这就意味着成功了60%!!!!(关键)。以例题来说,平均张数为10,原张数变为-1,-2,+7,-4,因为没有为0的数,所以从最左边出发,将-1移动到-2中,变为0,-3,+7,4,再讲-3向右移动……一次类推,直到全为0为止。没移动一次,步数便加1。关键是,负数怎么移动,其实,移动-x张牌,其实就是从另一堆中移动x张牌,步数相同。还有就是要过滤0,如排数为4,4,2,6,则减去平均数后为0,0,-2,2,就要从第三对开始移动。注意有些0是不能过滤的,如1,0,1,-2中的0。还有就是每次移动好都要过滤。如-2,2,1,3,-4,第一步后变为0,0,1,3,-4,可以省略第二堆的移动。

1
2
3
4
5
6
7
8
9
10
11
#include <iostream>  
using namespace std;
int main()
{
int a,p=0,js=0; cin >>a;int q[a];
for (int y=0;y<a;y++){cin >>q[y]; p+=q[y];} p/=a;
for (int y=0;y<a;y++)q[y]-=p;
for (int y=0;y<a;y++) {if (q[y]==0)continue; q[y+1]+=q[y]; js++; }
cout <<js;
return 0;
}

我的解法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
int sum=0,card[103],num,mean,no_count=0;
cin>>num;
for(int i=1;i<=num;i++) {cin>>card[i]; sum+=card[i];}
mean=sum/num;

int pointer=0,local_sum=0;
for(int i=1;i<=num;i++){
local_sum+=card[i];
pointer++;///我的思路是记录有没有一个 local_max==local_sum,如果有 local_sum,即pointer所指的那一堆,之前的就全部排好了,不需要再操心了
if(pointer==1 && card[i]==mean) {pointer=1; no_count++;}
///直接等于平均数的堆要拿出来特殊讨论,因为他们只有跟在已经排好序的堆后面的时候才不需要再经过一次移动,而前面的堆已经排好序的标志就是 pointer==1,这种情况下我们可以少移动一个,并且重新设置 pointer==1 代表前面的堆都有序
if(local_sum==pointer*mean && pointer!=1){
/// local_sum==pointer*mean 此时我们找到一个堆,可以使前面的所有堆获得符合要求的解,并且他只需要向别人输送牌,自己不需要接受,所以有一个 no_count++
/// pointer!=1 这是 local_sum 就是他本身,必然相等
no_count++;
pointer=0;
local_sum=0;
}
}
cout<<num-no_count;
}
CATALOG
  1. 1. 标解
  2. 2. 我的解法